package com.gitee.sop.sopauth.auth.impl;

import com.gitee.sop.sopauth.auth.*;
import com.gitee.sop.sopauth.auth.exception.LoginErrorException;
import com.i72.basic.CacheHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.apache.oltu.oauth2.common.message.types.ResponseType;
import org.apache.oltu.oauth2.common.utils.OAuthUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URISyntaxException;

/**
 * oauth2服务端默认实现
 *
 * @author tanghc
 */
@Service
@Slf4j
public class AccessTokenServiceImpl implements AccessTokenService {


    private static final String TOKEN_TYPE = "Bearer";
    public static final String APP_ID_NAME = "app_id";

    private OAuthIssuer oauthIssuer = new OAuthIssuerImpl(new MD5Generator());

    @Autowired
    private OAuth2Manager oauth2Manager;

    @Autowired
    private AppIdManager appIdManager;


    @Override
    public FetchTokenResult accessToken(FetchTokenParam fetchTokenParam, OAuth2Config authConfig) {

        // 表示client_id和client_secret是合法的

        String grant_type = fetchTokenParam.getGrant_type();
        if(GrantType.CLIENT_CREDENTIALS.toString().equals(grant_type)){

            if(appIdManager.isValidSecret(fetchTokenParam.getAppId(), fetchTokenParam.getSecret())) {
                TokenPair tokenPair = this.createNewToken();


                String organId=appIdManager.getOrganId(fetchTokenParam.getAppId());

                // 生成OAuth响应
                FetchTokenResult tokenResult = this.buildTokenResult(tokenPair, organId,authConfig);

                //保存token到redis:
                int expires_in=24*60*60;
                if(tokenResult.getExpires_in()>0){
                    expires_in=(int)tokenResult.getExpires_in();
                }
                String currentTokenRedisKey = String.format("current_appId_token_%s",fetchTokenParam.getAppId());

                String last_token = CacheHelper.cluster.getValue(currentTokenRedisKey);
                CacheHelper.cluster.setValue(tokenResult.getApp_auth_token(),fetchTokenParam.getAppId(),expires_in);
                CacheHelper.cluster.setValue(currentTokenRedisKey,tokenResult.getApp_auth_token(),expires_in);
                CacheHelper.cluster.setValue(last_token,fetchTokenParam.getAppId(),10*60);

                return tokenResult;
            }else{
                FetchTokenResult errorResult = new FetchTokenResult();
                errorResult.setError(OAuthError.TokenResponse.INVALID_GRANT);
                errorResult.setError_description("invalid appId and secret");
                return errorResult;
            }
        } else {
            FetchTokenResult errorResult = new FetchTokenResult();
            errorResult.setError(OAuthError.TokenResponse.INVALID_GRANT);
            errorResult.setError_description("invalid grant");
            return errorResult;
        }

    }

    /**
     * 刷新token后续操作
     *
     * @param oldTokenPair 老的token
     * @param newTokenPair 新的token
     * @param user         用户
     */
    protected void afterRefreshToken(TokenPair oldTokenPair, TokenPair newTokenPair, OpenUser user) {
        // 保存token
        oauth2Manager.addAccessToken(newTokenPair.getAccessToken(), newTokenPair.getRefreshToken(), user);

        // 删除老的accessToken
        oauth2Manager.removeAccessToken(oldTokenPair.getAccessToken());
        // 删除老的refreshToken
        oauth2Manager.removeRefreshToken(oldTokenPair.getRefreshToken());
    }

    /**
     * 创建新的token
     *
     * @return 返回新token
     */
    protected TokenPair createNewToken() {
        return this.createDefaultTokenPair();
    }

    /**
     * 返回刷新后token
     *
     * @param user         用户
     * @param oldTokenPair 旧的token
     * @return 返回新的token
     */
    protected TokenPair createRefreshToken(OpenUser user, TokenPair oldTokenPair) {
        return this.createDefaultTokenPair();
    }

    private TokenPair createDefaultTokenPair() {
        TokenPair tokenPair = new TokenPair();
        try {
            String accessToken = oauthIssuer.accessToken();
            String refreshToken = oauthIssuer.refreshToken();

            tokenPair.setAccessToken(accessToken);
            tokenPair.setRefreshToken(refreshToken);

            return tokenPair;
        } catch (OAuthSystemException e) {
            throw new RuntimeException(e);
        }
    }

    private FetchTokenResult buildTokenResult(TokenPair tokenPair,String organId,OAuth2Config auth2Config) {
        FetchTokenResult fetchTokenResult = new FetchTokenResult();
        fetchTokenResult.setApp_auth_token(tokenPair.getAccessToken());
        fetchTokenResult.setApp_refresh_token(tokenPair.getRefreshToken());
        fetchTokenResult.setOrgan_id(organId);
        fetchTokenResult.setExpires_in(auth2Config.getAccessTokenExpiresIn());
        fetchTokenResult.setRe_expires_in(auth2Config.getRefreshTokenExpiresIn());
        return fetchTokenResult;
    }

}
